"""
    实现一个方法，
    来判断一个正整数是否是2的整数次幂
    （如16是2的4次方，返回true；18不是2的整数次幂，则返回false），
    要求性能尽可能高。
"""


def is_pow_of_2(num):
    """
    创建一个中间变量temp，初始值是1。
    然后进入一个循环，每次循环都让temp乘以2，并和目标整数相比较，
    如果相等，则说明目标整数是2的整数次幂；
    如果不相等，则让temp增大1倍，继续循环并进行比较。
    当temp的值大于目标整数时，说明目标整数不是2的整数次幂。
    """
    temp = 1
    while temp <= num:
        if temp == num:
            return True
        temp = temp * 2
    return False


# 提高性能?
def is_pow_of_2_v2(num):
    """
    乘以2的操作改成向左移位，移位的性能比乘法高得多
    但是目前算法的时间复杂度仍然是O（logn），本质上没有变
    """
    temp = 1
    while temp <= num:
        if temp == num:
            return True
        temp = temp << 1
    return False


def is_pow_of_2_v3(num):
    """
    如果把2的整数次幂转换成二进制数，会有什么样的共同点？

    十进制     二进制             是否为2的整数次幂
    8          1000                 是
    16         10000                是
    32         100000               是
    64         1000000              是
    100        1100100              否


    这些2的整数次幂各自减1，再转化成二进制数，会有什么样的特点呢？

    十进制     二进制          原数值 - 1      是否为2的整数次幂
    8          1000              111               是
    16         10000             1111              是
    32         100000            11111             是
    64         1000000           111111            是
    100        1100100           1100011           否

    2的整数次幂一旦减1，它的二进制数的数字就全部变成了1


    这时候如果用原数值（2的整数次幂）和它减1的结果进行按位与运算，也就是 n &（n-1），会是什么结果呢?

    十进制     二进制          原数值 - 1     n &（n-1）     是否为2的整数次幂
    8          1000              111         0            是
    16         10000             1111        0            是
    32         100000            11111       0            是
    64         1000000           111111      0            是
    100        1100100           1100011     1100000      否
    :param num:
    按位的运算，都按位的运算，都是把参加运算的数的二进制形式进行运算。
        1.与运算：A与B值均为1时，A、B与的运算结果才为1，否则为0 （运算符：&）
        2.或运算：A或B值为1时，A、B或的运算结果才为1，否则为0  （运算符：|）
        3.异或运算：A与B不同为1时，A、B的预算结果才为1，否则为0  （运算符：^）
        4.按位翻转(按位取反)：将内存中表示数字的2进制数取反0取1，1取0 (运算符：~)
    """
    return num & (num - 1) == 0


print(is_pow_of_2(18))
print(is_pow_of_2(32))
print(is_pow_of_2_v3(32))
print(100 & 99)